﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<map>
#include<list>
using namespace std;
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void test1() {
	//1.1 C++98中一般数组和结构体可以用{}进行初始化
	//如：
	struct student {
		int _x;
		int _y;
	};

	int arr[] = { 1,2,3,4,5,6 };
	int arr1[4] = { 0 };
	student s = { 1,2 };

	//1.2 C++11中的{}
	// 
	// (1) C++11以后想统⼀初始化⽅式，试图实现⼀切对象皆可⽤{}初始化，{}初始化也叫做列表初始化。
	// (2) 内置类型⽀持，⾃定义类型也⽀持，⾃定义类型本质是类型转换，中间会产⽣临时对象，最后优化
	//了以后变成直接构造。
	// (3) {}初始化的过程中，可以省略掉 =
	// (4) C++11列表初始化的本意是想实现⼀个⼤统⼀的初始化⽅式，其次他在有些场景下带来的不少便
	//利，如容器push / inset多参数构造的对象时，{}初始化会很⽅便

	//如：
	//1.内置类型支持
	int x1 = { 3 };
	int x2{ 4 }; //省略=

	//2.自定义类型支持
	Date d1 = { 2024,10,23 }; //这里的本质是用{2024,10,23}
	             //构造一个Date临时对象，然后用该对象
                //拷贝构造d1,编译器优化后合二为一变成{ 2025, 1, 1}
                //直接构造初始化d1
    // 运⾏⼀下，我们可以验证上⾯的理论，发现是没调⽤拷⻉构造的
	//省略=：
	Date d2{ 2025,1,1 };

	const Date& d3 = { 2025,2,2 }; //这里d3引用的是{2025,2,2}
	                    //构造的临时对象，临时对象具有常性，要加const才能引用

	// 需要注意的是C++98⽀持单参数时类型转换，也可以不⽤{}
	Date d4 = { 2025 };   //因为有些参数是缺省参数，不用传
 	Date d5 = 2025;

	vector<Date> v;
	cout << 1 << endl;
	v.push_back(d1);
	v.push_back(Date(2025, 1, 1));
	// ⽐起有名对象和匿名对象传参，这⾥{}更有性价⽐
	v.push_back({ 2025, 1, 1 });
}
void test2() {
	//C++11中的std::initializer_list

	//1.上⾯的初始化已经很⽅便，但是对象容器初始化还是不太⽅便，⽐如⼀个vector对象，我想⽤N个
	  //值去构造初始化，那么我们得实现很多个构造函数才能⽀持，

	//2.C++11库中提出了⼀个std::initializer_list的类
	  //内部有两个指针分别指向数组的开始和结束,且initializer_list
	 ///也提供了迭代器遍历

	//3.容器⽀持⼀个std::initializer_list的构造函数，也就⽀持任意多个值构成的 {x1,x2,x3...} 进⾏
	//初始化。STL中的容器⽀持任意多个值构成的{ x1,x2,x3... } 进⾏初始化，就是通过
	//std::initializer_list的构造函数⽀持的。

	//STL中的容器都增加了一个initializer_list的构造
	//(1)vector (initializer_list<value_type> il, const allocator_type& alloc =
	//       allocator_type());
	//(2)list(initializer_list<value_type> il, const allocator_type & alloc =
	//     	 allocator_type());
	//(3)map(initializer_list<value_type> il, const key_compare & comp =
	// 	     key_compare(), const allocator_type & alloc = allocator_type())
	//注：这几个容器内部都是用initializer_list的迭代器遍历initializer_list对象来将
	//    数据插入到自身


	//initializer_list的使用：
	initializer_list<int> mylist = { 1,2,3,4,5,6 };
	for (auto num : mylist) {
		cout << num << " ";
	}
	cout << endl;

	// 这⾥begin和end返回的值initializer_list对象中存的两个指针
    // 这两个指针的值跟i的地址跟接近，说明数组存在栈上
	int i = 0;
	cout << mylist.begin() << endl;
	cout << mylist.end() << endl;
	cout << &i << endl;


	//vector的列表初始化：
	//1.直接构造
	// 这里{1,2,3,4,10}先构造出一个initializer_list对象，然后
	// v1直接调用构造函数
	vector<int> v1({ 1,2,3,4,10 });

	//2. 构造+拷贝构造 == 优化成直接构造
	// 这里{4,5,6,7,8,9}先生成一个initializer_list，然后通过构造
	//  函数构造出一个vector<int>的临时对象，然后用该对象拷贝构造出
	//  v2。
	vector<int> v2 = { 4,5,6,7,8,9 };
    
	//3.引用一个临时对象（具有常性,不可修改）
	const vector<int>& v3 = { 2,3,5,7,8,0 };
   
	vector<int> v4;
	v4 = { 6,7,8,9,0 }; //initializer_list也支持赋值


	//map的初始化列表：
	// pair的隐式类型转化及map的initializer_list构造。
	//1.构造
	//注：{ "dog","狗" }会先走隐式类型转化成pair类型
	map<string, string> m1({ {"dog","狗"},{"cat","猫"} });
	//2.构造+拷贝构造==优化为直接构造
	map<string, string> m2 = { {"pig","猪"},{"dragon","龙"} };
	for (auto num : m2) {
		cout << num.first << " " << num.second << endl;
	}

	//list也有同样用法

}
int main() {
	//test1();
	test2();
	return 0;
}